import {delay, designPage, iHTMLDivElement, reactive, useRefs, watch} from "@peryl/react-compose";
import {usePageConfig} from "../../micro/MicroApp.pageConfig";
import {$dialog, $message, Button, ButtonGroup, PageCard, PageCardContent, Segment, SegmentGroup, Space} from "plain-design";
import {CodeRender} from "./CodeRender";
import {DEMO_CODE2} from "./DEMO_CODE";
import './code-generator-edit-page.scss';
import {usePageService} from "../../modules/micro/usePageService";
import {AICodeEditor} from "./AICodeEditor";
import {codeGeneratorResourceGetter, iCodeGeneratorRecord, openCodeGenRecordEditor} from "./code-generator.utils";
import {transpileCode} from "./code-render.utils";
import {http} from "../../modules/plain-design/http";
import {pathJoin} from "@peryl/utils/pathJoin";
import html2canvas from "html2canvas";
import {base64toFile} from "@peryl/react-cms-editor";
import {DefaultGetSnapshot} from "../../modules/cms-visual-editor";

export default designPage(() => {

  const { nav, pageParam } = usePageService();

  usePageConfig(config => {config.hideNavigation = true;});

  const sourceCodeGeneratorRecord: iCodeGeneratorRecord | undefined = pageParam.codeGeneratorRecord;

  const { refs, onRef } = useRefs({ toolbar: iHTMLDivElement });

  const state = reactive({
    currentMode: 'mode_edit' as 'mode_edit' | 'mode_preview' | 'mode_compile',
    record: {
      ...sourceCodeGeneratorRecord,
      code: sourceCodeGeneratorRecord?.code ?? DEMO_CODE2
    } as iCodeGeneratorRecord,
    transformCodeString: '',
  });

  const handler = {
    handleSave: async (forceOpenRecordEditor: boolean) => {
      if (forceOpenRecordEditor || !state.record.title) {
        state.record = await openCodeGenRecordEditor(state.record);
      }
      state.currentMode = 'mode_preview';
      await delay(1000);
      state.record.image = await (async () => {
        const targetElement = refs.toolbar!.nextElementSibling as HTMLElement;
        const canvas = await html2canvas(targetElement, { useCORS: true });
        const base64 = canvas.toDataURL('image/jpg', 1);
        const file = base64toFile(base64);
        return await DefaultGetSnapshot({ element: targetElement, file });
      })();
      const data = await http.post<{ result: any }>(pathJoin('code_gen', !!state.record.id ? 'update' : 'insert'), { row: state.record });
      state.record = data.result;
      $message.success('保存成功');
    },
    handleEditRecord: async () => {
      await handler.handleSave(true);
    },
  };

  watch(() => (state.record.code ?? '') + state.currentMode, async () => {
    if (state.currentMode !== 'mode_compile' || !state.record.code?.trim().length) {return '';}
    state.transformCodeString = (await transpileCode({ code: state.record.code, getResource: codeGeneratorResourceGetter }));
    console.log(state.transformCodeString);
  });

  const renderMode = {
    mode_compile: () => (
      <PageCard full>
        <PageCardContent full noPadding>
          <AICodeEditor modelValue={state.transformCodeString}/>
        </PageCardContent>
      </PageCard>
    ),
    mode_edit: () => (
      <PageCard full>
        <PageCardContent full noPadding>
          <AICodeEditor v-model={state.record.code}/>
        </PageCardContent>
      </PageCard>
    ),
    mode_preview: () => <CodeRender code={state.record.code}/>,
  };

  return () => <>
    <div className="code-generator-edit-page-toolbar" ref={onRef.toolbar}>
      <Space size="mini">
        <ButtonGroup>
          <Button label="返回" icon="pi-left" onClick={() => nav.back()}/>
          <Button label="编辑信息" icon="pi-edit" onClick={handler.handleEditRecord}/>
          <Button label="保存" icon="pi-save" mode="fill" asyncHandler={() => handler.handleSave(false)}/>
        </ButtonGroup>
        <SegmentGroup v-model={state.currentMode}>
          <Segment label="编辑" val="mode_edit"/>
          <Segment label="预览" val="mode_preview"/>
          <Segment label="编译" val="mode_compile"/>
        </SegmentGroup>
      </Space>
    </div>
    {renderMode[state.currentMode]()}
  </>;
});
